package client

import (
	"time"

	"hundsun.com/hsl/hschain/common/types"

	"hundsun.com/hsl/hschain/common/log/logging"
	pbledger "hundsun.com/hsl/hschain/protos/ledger"
	"hundsun.com/hsl/hschain/store/db"
	"hundsun.com/hsl/hschain/store/extend/ledger"
)

// DB 消息通道协议实现
type DB struct {
	// 消息队列
	dbm    db.Database
	logger logging.Log
	option *TimeoutOption
}

// New ClientProtocolAPI interface
func New(dbm db.Database, option *TimeoutOption, logger logging.Log) (ProtocolAPI, error) {
	if dbm == nil || logger == nil {
		return nil, types.ErrInvalidParam
	}
	c := &DB{}
	c.dbm = dbm
	c.logger = logger
	if option != nil {
		c.option = option
	} else {
		c.option = &TimeoutOption{
			SendTimeout: time.Duration(-1),
			WaitTimeout: time.Duration(-1),
		}
	}
	return c, nil
}

// GetBlocks get block detail from blockchain
func (q *DB) GetBlocks(start, end uint64) ([]*pbledger.Block, error) {
	if start > end {
		err := types.ErrInvalidParam
		q.logger.Error("GetBlocks", "Error", err)
		return nil, err
	}

	ld, err := ledger.NewLedger(q.dbm)
	if err != nil {
		q.logger.Error("GetBlocks newledger", "Error", err)
		return nil, err
	}

	return ld.GetBlocks(start, end)
}

//SaveBlock 保存区块
func (q *DB) SaveBlock(block *pbledger.Block) error {
	ld, err := ledger.NewLedger(q.dbm)
	if err != nil {
		q.logger.Error("GetBlocks newledger", "Error", err)
		return err
	}

	return ld.SaveBlock(block)
}

//GetBlock 获取区块
func (q *DB) GetBlock(num uint64) (*pbledger.Block, error) {
	ld, err := ledger.NewLedger(q.dbm)
	if err != nil {
		q.logger.Error("GetBlocks newledger", "Error", err)
		return nil, err
	}

	return ld.GetBlock(num)
}

//GetLastBlockheader 获取最新区块头
func (q *DB) GetLastBlockheader() (*pbledger.BlockHeader, error) {
	ld, err := ledger.NewLedger(q.dbm)
	if err != nil {
		q.logger.Error("GetBlocks newledger", "Error", err)
		return nil, err
	}
	height, err := ld.GetBlockNumber()
	if err != nil {
		q.logger.Error("GetBlockNumber ", "Error", err)
		return nil, err
	}
	block, err := ld.GetBlock(height)
	if err != nil {
		q.logger.Error("GetBlock ", "Error", err)
		return nil, err
	}
	return block.GetHeader(), nil
}

//GetExecutedBlock 获取执行后的区块
func (q *DB) GetExecutedBlock(num uint64) (*pbledger.ExecutedBlock, error) {
	// TODO
	return nil, nil
}

//GetExecutedBlocks 批量获取执行后的区块
func (q *DB) GetExecutedBlocks(start, end uint64) ([]*pbledger.ExecutedBlock, error) {
	// TODO
	return nil, nil
}

//GetMaxExecutedBlock 获取最新执行后的区块
func (q *DB) GetMaxExecutedBlock() (*pbledger.ExecutedBlock, error) {
	// TODO
	return nil, nil
}

//GetMaxExecutedBlockNumber 获取最新执行后的区块号
func (q *DB) GetMaxExecutedBlockNumber() (uint64, error) {
	// TODO
	ld, err := ledger.NewLedger(q.dbm)
	if err != nil {
		q.logger.Error("GetExecutedBlocks newledger", "Error", err)
		return 0, err
	}
	return ld.GetMaxExecutedBlockNumber()
}

//GetConsensusStepRecords 获取共识记录
func (q *DB) GetConsensusStepRecords() (*pbledger.ConsensusStepRecords, error) {
	//TODO
	return nil, nil
}
